package com.bellszhu.elasticsearch.plugin.util;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.StringReader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.*;
import java.util.Objects;

/**
 * Created by Gary on 2020-05-20.
 *
 * @author Gary
 * @version 3.1.5.M1
 * @since 3.1.5.M1
 */
public class JDBCUtils {

    private static Logger logger = LogManager.getLogger("dynamic-synonym");

    public static Connection getConnection(String jdbcUrl, String userName, String password) {
        logger.debug("get jdbc connection jdbcUrl: {}, userName : {}, password: {}", jdbcUrl, userName, password);
        final Connection[] connection = {null};
        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
            try {
                Class.forName("oracle.jdbc.OracleDriver");
                String decryptPassword = decryptPassword(password);
                logger.debug("decrypt password {}", decryptPassword);
                connection[0] = DriverManager.getConnection(jdbcUrl, userName, decryptPassword);
            } catch (ClassNotFoundException | SQLException e) {
                logger.error("get jdbc connection error:", e);
            }
            return null;
        });
        return connection[0];
    }

    /**
     * 获取最大版本号
     *
     * @param connection jdbc connection
     * @return lastVersion
     */
    public static long getLastVersion(Connection connection) {
        long maxVersion = 0;
        Statement statement = null;
        ResultSet resultSet = null;
        try {
            statement = connection.createStatement();
            String sql = "SELECT max(version) VERSION FROM dynamic_synonym_rule";
            resultSet = statement.executeQuery(sql);
            while (resultSet.next()) {
                maxVersion = resultSet.getLong("VERSION");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeQuietly(connection, statement, resultSet);
        }
        return maxVersion;
    }

    public static StringReader querySynonymRules(Connection connection, long lastVersion) {
        logger.debug("query synonym from jdbc. version is {}", lastVersion);
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {

            String sql;
            sql = "SELECT RULE FROM DYNAMIC_SYNONYM_RULE WHERE VERSION <=? AND STATUS = 1";
            statement = connection.prepareStatement(sql);
            statement.setLong(1, lastVersion);
            resultSet = statement.executeQuery();
            logger.debug("query result set is {}", resultSet);
            StringBuilder sb = new StringBuilder();
            while (resultSet.next()) {
                String line = resultSet.getString("RULE");
                logger.debug("get jdbc synonym: {}", line);
                sb.append(line).append(System.getProperty("line.separator"));
            }
            logger.debug("the synonym string is {}", sb.toString());
            return new StringReader(sb.toString());
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            closeQuietly(connection, statement, resultSet);
        }
        return new StringReader("");
    }

    private static void closeQuietly(Connection connection, Statement statement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException ignored) {
            }
        }
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException ignored) {
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException ignored) {
            }
        }
    }

    private static String decryptPassword(String password) {
        if (password == null || Objects.equals("", password)) {
            return password;
        } else {
            try {
                DESPlus des = new DESPlus();
                password = des.decrypt(password);
                return password;
            } catch (Exception e) {
                return password;
            }
        }
    }

}
